perm filename PINTRP.PAL[PNT,HE]3 blob sn#467714 filedate 1979-08-19 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00019 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	 data trasnfer macros: SNDINT,SNDFP
C00004 00003	 temporary resting place for routines displaced from INTERP.PAL[AL,HE]
C00006 00004	 data transfer : PUSHINTI,ARTVAL,RTVAL,AGTVAL,RTARR,FRVAL
C00017 00005		RTLEVS - returns leveloffset info of stack in integer buffer
C00019 00006		PAFFIX,PUNFIX
C00024 00007	 display: DISVT05
C00025 00008	 PSPROUT: used with COBEGIN
C00027 00009	 RCASE: used with CASE
C00029 00010	 relative jumps: RFRCHK,RJMP,RJMPC
C00032 00011	 printing routines: RPRINT,PRVAL,PRINTI
C00037 00012	 supplementary motions: pmove,tadrive,tddrive,gather,rforce,setstf
C00041 00013	 supplementary functions: uparrow,dwnarrow,alpha,dollar,swap,vneg,vsmul,ftof
C00045 00014	 functions: sqrt,sin,cos,asin,acos,tan,atan2,log,exp
C00046 00015	 armreach- can arm reach here?
C00048 00016	 procedure handling: GTBLK
C00050 00017	 more stack ops: gtint,gvals,chngs
C00052 00018	 components of data types: CHCMP,GTCMP
C00055 00019	 return from POINTY : pdone 
C00056 ENDMK
C⊗;
COMMENT ⊗ data trasnfer macros: SNDINT,SNDFP
	⊗

.MACRO	SNDINT X
	MOV  X,@INTPTR
	ADD  #2,INTPTR
	.ENDM

.MACRO	SNDFP X
	STF  X,@FPPTR
	ADD  #4,FPPTR
	.ENDM

.MACRO	SNDFIN X
	STCFI X,@INTPTR
	ADD   #2,INTPTR
	.ENDM
;; routine for transferring a block of fp data from 11 to 10
;; R0 has address of data, R1 has # FP numbers to transfer
;; R0,R1,AC0 are garbaged

FTAPE:	TST	R1
	BEQ	2$
	PUSH	<R2>
	MOV	FPPTR,R2
1$:	LDF	(R0)+,AC0
	STF	AC0,(R2)+
	SOB	R1,1$
	MOV	R2,FPPTR
	POP	<R2>
2$:	RTS	PC
; temporary resting place for routines displaced from INTERP.PAL[AL,HE]
COMMENT ⊗
COPY:	FETCH R0	;Pick up argument.
COPY0:	ADD R0,R0	;Double R0 to make it in bytes
	ADD R3,R0	;R0 ← LOC[stack element to be copied to top]
	MOV (R0),-(R3)	;Copy it onto top of stack.
	CCC		;Clear condition code.
	RTS PC		;Done
⊗;
COMMENT ⊗
PUSHSCI:
; The argument is a (2 word) floating point number. Make a scalar out of it and
; push that scalar onto stack.

	LDF @IPC(R4),AC0;get the floating point arg
	ADD #4,IPC(R4)	;Bump IPC--TWO TIMES !
	JSR PC,NOCMP
      	JSR PC,GETSCA	;R0 ← -(R3) ← LOC[new scalar block]
	STF AC0,@(R3)	;Store result
	JSR PC,YESCMP
	CCC		;Clear condition code.
	RTS PC		;Done
	⊗;
COMMENT	⊗ data transfer : PUSHINTI,ARTVAL,RTVAL,AGTVAL,RTARR,FRVAL
 routines to facilitate data transfer to POINTY interface
	XX is scalar index; Y is leveloffset of array element

	AGTVAL XX,Y	= PUSHINTI XX; GTVAL Y
	ACHNGE XX,Y	= PUSHINTI XX; CHNGE Y
	ARTVAL XX,Y	= AGTVAL XX,Y; RTVAL
	RTARR Y	 returns #elements and value of array offset Y
	RTVAL is used to transfer the top element of stack to the return buffer
	⊗;
PUSHINTI:
; The argument is an integer. Make a scalar out of it and
; push that scalar onto stack.

	FETCH R0
	LDCIF R0,AC0	;convert to real
	JSR PC,NOCMP
      	JSR PC,GETSCA	;R0 ← -(R3) ← LOC[new scalar block]
	STF AC0,@(R3)	;Store result
	JSR PC,YESCMP
	CCC		;Clear condition code.
	RTS PC		;Done


AGTVAL:	JSR	PC,PUSHINTI	; get value of index to array
	JMP	GTVAL		; now get the offset of the array

CCHNGE:	CLR	R0
	JSR	PC,COPY0	; copy value of top element in stack
	JMP	CHNGE		; now do the assignment

CACHNG:	CLR	R0
	JSR	PC,COPY0	; copy value of top element in stack
ACHNGE:	JSR	PC,PUSHINTI	; get value of index to array
	JMP	CHNGE		; now update value of the array

CRTVAL:	MOV	(R3),R0		; return top of stack without popping
	JMP	RTVAL0

FRVAL:	FETCH	<R0>		; get offset
FRVAL0:	JSR	PC,GETARG	; R0←LOC[environment entry]
	BIT	#HDRTYP,(R0)	; check header exists
	BNE	1$		
	JSR	PC,MFRAME	; make frame header
1$:	MOV	2(R0),R0	; R0←LOC[frame header]
	PUSH	<R0>		; save R0
	ADD	#CALCS,R0	; R0←LOC[beginning of calculator list]
2$:	MOV	(R0),R0		; R0←LOC[next calcualtor to check]
	BEQ	6$		; Make sure there is something there
	BIT	#AFXTYP,TYPE(R0); Make sure it is an affixment
	BEQ	2$
	BIT	#FRAME2,TYPE(R0); Check if second frame in affixment
	BNE	2$		; If not, go check the next calculator
3$:	BIT	#EXPTRN,TYPE(R0); Is it an explicit trans?
	BEQ	4$
	MOV	@TRANS(R0),R0	; R0←LOC[trans]
	BR	5$
4$:	MOV	TRANS(R0),R0	; implicit trans
5$:	POP	<R1>		; get SP to correct state
	JMP	PC,RTVAL0	; retrun from RTVAL0
6$:	POP	<R0>
	JSR	PC,NOCMP
	CALL	GETVAL,<R0>	; R0←Value
	JSR	PC,YESCMP
	JMP	PC,RTVAL0	; return from RTVAL0
comment ⊗
RTARR:	FETCH	R0		; get offset of the array we are interested in
	PUSH	<R2>		; save R2
	JSR	PC,GETENV	; get environment pointer in R0
	MOV	2(R0),R2	; R2←LOC[array header]
	MOV	(R2)+,R0	; R0←# of dimensions of array
	CLR	-(SP)		; compute number of elements in array
1$:	MOV	(R2)+,R1	; R1←(ub[i]- lb[i])*mult[i]
	SUB	(R2)+,R1	;
	INC	R1		; add 1
	MUL	(R2)+,R1	;
	ADD	R1,(SP)		; and add it to elements so far
	SOB	R0,1$		; repeat for all the dimensions
	MOV	(SP)+,R1	; R1←# of elements in array
	SNDINT	R1		; send it back to 10
	PUSH	<R2>		; save current environment entry
	⊗;

RTARR:	JSR	PC,ARRSIZ	; get array size
				; R0←array size, R1←LOC[first env entry]
	SNDINT	R0
	PUSH	<R2>
	PUSH	<R1>		; (SP)←LOC[env entry]
	MOV	R0,R2		; R2←#elements
2$:	MOV	(SP),R0		; R0←LOC[env entry]
	ADD	#4,(SP)		; (SP)←next environment entry
	JSR	PC,GVAL1	; (R3)←LOC[value cell]
	JSR	PC,RTVAL	; return the element value
	SOB	R2,2$
	TST	(SP)+		; dont need the value of last push
	POP	<R2>		; get back the initial value of R2
	CCC
	RTS	PC		; and return

; following routine returns parameter values to the 10 and returns
; the following register values:
;	R0←#elements in the array
;	R1←LOC[env entry for first element]


RTPARS:	FETCH	R0		; get offset of the array we are interested in
	SNDINT	#XRTPARS	; send back info to 10
	SNDINT	R0		; send back arrayoffset number to 10
	PUSH	<R2>		; save R2
	PUSH	<INTPTR>	; save location of INTPTR for later use
	ADD	#2,INTPTR	; increment the value of intptr
	JSR	PC,GETENV	; get environment pointer in R0
	MOV	2(R0),R2	; R2←LOC[array header]
	MOV	(R2)+,R0	; R0←# of dimensions of array
	SNDINT	R0		; return # of dimensions
	CLR	-(SP)		; compute number of elements in array
1$:	MOV	(R2)+,R1	; R1←(ub[i]- lb[i])*mult[i]
	SNDINT	R1		; return upper bound
	SNDINT	(R2)		; return lower bound
	SUB	(R2)+,R1	;
	SNDINT	(R2)		; return multiplier
	INC	R1		; add 1
	MUL	(R2)+,R1	;
	ADD	R1,(SP)		; and add it to elements so far
	SOB	R0,1$		; repeat for all the dimensions
	MOV	(SP)+,R1	; R1←# of elements in array
	POP	<R0>
	MOV	R1,(R0)		; and send it to the buffer
	MOV	R1,R0		; R0←#of elements
	MOV	R2,R1		; R1←LOC[env entry of first element]
	POP	<R2>		; get back the initial value of R2
	CCC
	RTS	PC		; and return

ARRSIZ:	FETCH	R0		; takes array offset in R0 and returns
				; R0←#elements in array
				; R1←LOC[env entry of first element]
ARRSZ0::PUSH	<R2>
	JSR	PC,GETENV	; get environment pointer in R0
	MOV	2(R0),R2	; R2←LOC[array header]
	MOV	(R2)+,R0	; R0←#dimensions of array
	CLR	-(SP)		; compute # of elements in array
1$:	MOV	(R2)+,R1	; R1←(UB[i]-LB[i])*mult[i]
	SUB	(R2)+,R1
	INC	R1
	MUL	(R2)+,R1
	ADD	R1,(SP)
	SOB	R0,1$
	MOV	(SP)+,R0
	MOV	R2,R1
	POP	<R2>
	CCC
	RTS	PC

SC0:	MOV	#NILVEC,-(R3)
	JMP	SNEG
VT0:	MOV	#NILVEC,-(R3)
	JMP	VNEG
TR0:	PUSH	<R2>
	MOV	#NILTRN,-(R3)
	MOV	#NILVEC,-(R3)
	JSR	PC,VNEG
	JSR	PC,TMAKE
	POP	<R2>
	RTS	PC

ARRINI:	JSR	PC,RTPARS	; get the array size and LOC[env entry first]
	PUSH	<R2>
	MOV	R1,-(SP)	; (SP)←LOC[first env entry]
	MOV	R0,R2
	MOV	(SP),R0
	CMP	#SCLTYP,(R0)	; scalar array
	BNE	2$
	MOV	#SC0,1$
	BR	4$
2$:	CMP	#VECTYP,(R0)	;vector array
	BNE	3$
	MOV	#VT0,1$
	BR	4$
3$:	MOV	#TR0,1$		; niltrans
4$:	JSR	PC,@1$
	MOV	(SP),R0
	ADD	#4,(SP)
	JSR	PC,CHNG1
	SOB	R2,4$
	TST	(SP)+
	POP	<R2>
	CCC
	RTS	PC

DATA
1$:	0
CODE
ARTVAL:	JSR	PC,AGTVAL	; get the value of the array element
RTVAL:				; now output the value
	MOV	(R3)+,R0	; pop the top element  R0←loc[value cell]
RTVAL0:	MOV	#1,R1		; counter for counting number of elements
	CMPB	#TRNID,TAGID(R0)	;A trans?
	BEQ	1$
	CMPB	#VCTID,TAGID(R0)	;A vector?
	BEQ	2$
	BR	3$			;Must be a scalar
1$:	JSR	PC,EULER
	MOV	#EDAT,R0
	MOV	#4,R1
2$:	ADD	#2,R1

3$:	LDF	(R0)+,AC0		;load element into AC0
	STF	AC0,@FPPTR		;move it into return buffer
	ADD	#4,FPPTR		;update the pointer in the return buffer
	SOB	R1,3$			;get the next element
	RTS	PC

EULER:	MOV	#EDAT,R1
	JSR	PC,@LEULER	; now recorrect
	MOV	#EDAT+14,R1	; value of THETA
	LDF	(R1),AC0	; get value of O computed by euler in armcode
	SUBF	F90,AC0
	STF	AC0,(R1)+
	LDF	(R1),AC0	; PHI=A+90
	ADDF	F90,AC0
	STF	AC0,(R1)
	RTS	PC

DATA
F90:	.FLT2	90.0
F180:	.FLT2	180.0
EDAT:	.BLKW	30
YHAT:	.FLT2	0.0,1.0,0.0,1.0
ZHAT:	.FLT2	0.0,0.0,1.0,1.0
CODE
;	RTLEVS - returns leveloffset info of stack in integer buffer

RTLEVS:
COMMENT ⊗ Returns offset of top element in the stack if simple variable: if it is
	an array, returns the offset and the index sequentially.  This does not
	affect the stack. R0 and R1 are garbaged.
	⊗
	MOV R3,R1		;Use temporary stackpointer
	LDF @(R1)+,AC0		;Get value of top element of stack
	STCFI AC0,R0		;convert into integer and put in R0
	MOV R0,@INTPTR		;and store into integer buffer
	ADD #2,INTPTR		;and increment integer buffer pointer
	PUSH <R1>		;Since GETENV will clobber it
	JSR PC,GETENV		;Get the environment pointer in R0
	POP  <R1>		;TO recover R1
	BIT #ARYTYP,(R0)	;Do we have an array to access?
	BEQ 10$
	PUSH <R2>
	MOV 2(R0),R2		;R2 ← LOC[array header]
	MOV (R2)+,R0		;R0 ← # of dimensions of array
	POP  <R2>
3$:	LDF @(R1)+,AC0		;Get value of subscript
	STCFI AC0,@INTPTR	;Ship it into integer buffer
	ADD #2,INTPTR		;update the pointer
	SOB R0,3$		;Do all the subscripts
10$:	RTS PC			;Return with R0 and R1 garbaged
;	PAFFIX,PUNFIX

PAFFIX:
COMMENT ⊗ AFFIX together the two currently top elements
	and return their offsets in the integer buffer.
	⊗
	SNDINT #XAFFIX		;return affix code
	JSR PC,RTLEVS		;return the offset to the 10
	JSR PC,GTINT		;Get first frame offset
	JSR PC,GETARG		;R0 ← LOC[environment entry]
	BIT #HDRTYP,(R0)	;Test access type
	BNE 1$
	JSR PC,MFRAME		;If necessary make a new frame header
1$:	MOV 2(R0),R2		;R2 ← LOC[first frame header]
	JSR PC,RTLEVS		;return the offset to he 10
	JSR PC,GTINT		;Get second frame offset
	JSR PC,GETARG		;R0 ← LOC[environment entry]
	BIT #HDRTYP,(R0)	;Test access type
	BNE 2$
	JSR PC,MFRAME		;If necessary make a new frame header
2$:	MOV 2(R0),R1		;R1 ← LOC[second frame header]
	MOV @(R4),@INTPTR	;Get affixment code and return it
	ADD #2,INTPTR		;increment the integer pointer
	JMP AFFIX0		;jump into main affix routine and return from there

PUNFIX:
COMMENT ⊗ return the offsets of the two top elements on the
	stack and unfix them
	⊗
	MOV #2,4$
	SNDINT #XUNFIX		;return unfix code
	JSR PC,RTLEVS		;return offset to the 10
	JSR PC,GTINT		;Get first frame offset
	JSR PC,GETARG		;R0 ← LOC[environment entry]
	BIT #HDRTYP,(R0)	;Check header exists
	BEQ 1$			;  if not quit
	MOV 2(R0),R2		;R2 ← LOC[first frame header]
	DEC 4$
1$:	JSR PC,RTLEVS		;return offset of the second frame
	JSR PC,GTINT		;Get second frame offset
	JSR PC,GETARG		;R0 ← LOC[environment entry]
	BIT #HDRTYP,(R0)	;Check header exists
	BEQ 3$			;  if not quit
	MOV 2(R0),R1		;R1 ← LOC[second frame header]
	DEC 4$
2$:	BNE 3$
	JMP UNFIX0		; jump into main interpreter routine returning from there
3$:	RTS PC			; return from here

DATA
4$:	0
CODE
; display: DISVT05

DISVT05:
	FETCH <R0>
	TST R0			;R0=0 → display - R0=1 → nodisplay
	BNE 1$			;go to stop display
	MOVB #COFF+30,CURYXAL	;trick display routine to think we are at bottom
	MOV #1,FRMDDT		;forces display to update titles
1$:	MOV R0,DSPOK
	RTS PC
; PSPROUT: used with COBEGIN

PSPROUT:
	FETCH <R2>	;R2←# of statements
	MOV R2,R0
	ASH #1,R0
	INC R0
	JSR PC,GTFREE
	MOV R2,R1	; R1← # of interpreters to spawn
	PUSH <R0>	; save offset of new buffer	(1)
	PUSH <IPC(R4)>	;save current value of ipc	(2)
1$:	FETCH <R2>	;get the offset from beginning of sprout
	ASH #1,R2	;get byte offset
	ADD (SP),R2	;add the absolute address
	MOV R2,(R0)+	;stick it into new buffer
	FETCH <(R0)+>	;increment the zero - better be zero
	SOB R1,1$
	FETCH <(R0)+>	; increment one more term, better be zero
	TST (SP)+	; pop value of old ipc		(1)
	MOV IPC(R4),R1	; save current IPC value
	MOV (SP),IPC(R4); change ipc value to beginning of buffer
	PUSH <R1>	; and put old ipc value into the stack	(2)
	JSR PC,SPROUT	;jump into main AL routine
	POP <IPC(R4)>	;restore the ipc value		(1)
	POP <R0>	;R0←address of buffer		(0)
	JSR PC,RLFREE	;release the buffer
	CCC		;Clear condition code.
	RTS PC		;Done
; RCASE: used with CASE
COMMENT ⊗ this routine assumes that the code following is similar to that
	following the AL case statement, including range numbers. However, labels
	are assumed to be relative to the first label, so that this routine sets
	up a new temporary block with the absolute addresses and
	then calls AL CASE statement before returning to release the block
	⊗;

RCASE:	FETCH <R2>	; R2←range
	MOV R2,R0
	BPL 1$		; get the absolute value
	NEG R0
1$:	ADD #2,R0	; # of labels = R0 + 1, so add 1 for the extra label and
			; 1 for the value of R2
	PUSH <R0>	; (1)
	JSR PC,GTFREE	; get a block of free storage
	POP <R1>	; (2)
	DEC R1		; R1← range +1 ,i.e. # of labels
	PUSH <R0>	; save address of free storage block(1)
	PUSH <IPC(R4)>	; save current IPC(2)
	MOV R2,(R0)+	; 1st word in block=signed range
2$:	FETCH <R2>
	ASL R2		; change relative position into bytes
	ADD (SP),R2	; ipc address
	MOV R2,(R0)+	; and push into the block
	SOB R1,2$	; do for all labels
	TST (SP)+	; pop top element, dont need address anymore(1)
	MOV (SP),IPC(R4); put address of this new auxilliary block of labels into ipc
	JSR PC,CASE	; and jump into AL's case statement
	POP <R0>	; now go release the space(0)
	JSR PC,RLFREE
	CCC
	RTS PC
; relative jumps: RFRCHK,RJMP,RJMPC
COMMENT ⊗ These routines are parallel to the jump and transfer of control
	routines in AL.  The relative jumps are needed to produce
	position independent pcode for the bodies of procedures
	⊗

RFRCHK:		; copied from FORCHK in INTRP.PAL
;Assume that the stack has, from surface in, the increment, the
;  final value, and the control variable's value, all of which are
;  scalar values.  If (FINAL-CONVAR)*(INCREMENT) ≥ 0 then this is a
;  no-op; otherwise, jump to the destination. 
;Arguments:  destination.	***** offset for control variable, destination *****
;******	MOV 4(R3),-(R3)	;Copy the control variable's value
;******	JSR PC,CHNGE	;Go update it
	LDF @2(R3),AC0	;AC0 ← final value
	SUBF @4(R3),AC0	;AC0 ← final - current
	MULF @(R3),AC0	;AC0 ← (final - current)*increment
	FETCH R0	;R0 ← destination offset ******** differs from FORCHK
	ASL R0		; to change to bytes
	CFCC
	BGE 1$		;Shall this be a no-op?
	BACKIPC		; since IPC is now pointing to next instruction
	ADD R0,IPC(R4)	;No; set new IPC. ******* in FORCHK this is MOV
;******	ADD #6,R3	;Pop the inc, final & control var off of the stack ****
1$:	CLR R0
	RTS PC		;Done

RJMP:
;Takes one argument: the relative offset of new address.
	MOV @IPC(R4),R0	; get the offset
	ASL R0		; change to bytes
	ADD R0,IPC(R4)	; increment IPC by the offset
	CCC		;Clear condition code.
	RTS PC		;Done

RJMPC:	;Parallel to JUMPC in INTERP.PAL[AL,HE]
	LDF	@(R3)+,AC0	;Get value of boolean
	CFCC			;copy condition codes
	BEQ	1$		;if false succeed - take branch
	BMPIPC			;skip over address
	RTS	PC		; & return
1$:	MOV	@IPC(R4),R0	; get the offset
	ASL	R0		; change to bytes
	ADD	R0,IPC(R4)	; branch
	RTS	PC		; & return

; printing routines: RPRINT,PRVAL,PRINTI

PRINTI:	FETCH <-(SP)>	; string printing this will replace RPRINT
			; (SP)←# of words to be printed
	ASL (SP)	; convert to bytes
	MOV @IPC(R4),R0	; R0←starting address of string
	ADD (SP)+,@IPC(R4)	; update the IPC
	JMP PRINT0

RPRINT:	MOV @IPC(R4),R0
	ASL R0
	ADD IPC(R4),R0	; put absolute address into R0 of string
	BMPIPC
	JMP PRINT0

TACK:
COMMENT ⊗ R1 = LOC[ascie string to tack on], R0 = LOC[where to put
it].  Returns R0 ← next location available in destination string.  ⊗
	MOVB (R1)+,(R0)+;Copy a byte
	BNE TACK	;Repeat while necessary
	DEC R0		;Go back past the null
	RTS PC		;Done

       .MACRO TACKST B	;tack the string B
	MOV #B,R1
	JSR PC,TACK
       .ENDM

       .MACRO TACKC B	;tack the character B
	MOVB #B,(R0)+	;move in the value
       .ENDM

; following routines are used to get a different form for printing
; R0 will point to next place in the string
PRVAL:	PUSH <R2>	;save R2
	EVWAIT CSLEVT
	MOV #4,R0	
	MOV #2,R1	; set format parameters to 2 dec places and squueze out blanks
	JSR PC,FORMAT	; use format to squeeze out blanks
	FETCH <R1>	; get type of printing
	ASH #1,R1	; TIMES 2
	MOV #OUTBUF,R0	; set R0←start of buffer
	JSR PC,@1$-2(R1); call appropriate routines to build up string
	CLRB (R0)	; ensure last character is a null to get rid of garbage
	MOV #OUTBUF,R0	; now print it
	JSR PC,TYPSTR
	JSR PC,RSTFOR	; restore format
	EVSIG CSLEVT
	POP <R2>	; restore r2
	CCC
	RTS PC
DATA
1$:	PRSCA
	PRVEC
	PRROT
	PRTRN
	PRFRM
CODE

PRSCA:	MOV (R3)+,R2	;R2←LOC[value cell]
PRREAL:	LDF (R2)+,AC0
	JSR PC,CVF	; go the conversion
	RTS PC

PRVEC:	MOV (R3)+,R2
PVECT:	TACKST VNAMEL	; tack "VECTOR("
	JSR PC,PRREAL	; tack first value
	TACKC COMMA
	JSR PC,PRREAL	; second value
	TACKC COMMA
	JSR PC,PRREAL	; third value
	TACKC ')	;")"
	RTS PC


PRROT:	PUSH <R0>
	MOV (R3)+,R0
	MOV #EDAT,R1
	JSR PC,EULER	; change to EULER angles
	MOV #EDAT,R2	; correct address for R2
	POP <R0>
PROT:	TACKST ROTZHC	; tack ROT(ZHAT,
	JSR PC,PRREAL	; value
	TACKC ')
	TACKC '*
	TACKST ROTYHC	; print ROT(YHAT,
	JSR PC,PRREAL
	TACKC ')
	TACKC '*
	TACKST ROTZHC	; print ROT(ZHAT,
	JSR PC,PRREAL
	TACKC ')
	RTS PC

PRTRN:	MOV #TNAMEL,R1	; print "TRANS("
	JMP PRFRM0

PRFRM:	MOV #FNAMEL,R1	; print "FRAME("
PRFRM0::JSR PC,TACK
	JSR PC,PRROT	; use common code with PRROT to compute euler angles
			; and tack the rot part
	TACKC COMMA	; output a comma
	JSR PC,PVECT	; print out the vector part
	TACKC ')	; print out right paren
	RTS PC


DATA
VNAMEL:  .ASCIZ /VECT(/
TNAMEL:: .ASCIZ /TR(/
FNAMEL:: .ASCIZ /FR(/
ROTZHC:: .ASCIZ /ROT(Z,/
ROTYHC:: .ASCIZ /ROT(Y,/
.EVEN
CODE
; supplementary motions: pmove,tadrive,tddrive,gather,rforce,setstf
RPMOVE:	MOV	LRPMOVE,R2	;set for position independent pcode
	JMP	MOVSTA		; used to be MOVST2

RTADRIVE:			; absolute drive
	MOV	LRTADRIVE,R2
	JMP	MOVSTA		; used to be MOVST2

RTDDRIVE:			; relative drive
	MOV	LRTDDRIVE,R2
	JMP	MOVSTA		; used to be MOVST2

RCENTER:
	MOV	LRCENTER,R2
	JMP	MOVSTA		; used to be MOVST2

COMMENT ⊗	used to return numbers for move
	also uncomment pg 19 ln 99 of interp.pal
MOVST2:	MOV	#XMOVE,@INTPTR	;code for move
	MOV	INTPTR,SVPTR	;save the current pointer
	ADD	#2,INTPTR	;increment pointer
	MOV	INTPTR,-(SP)	;save the pointer
	CLR	RPFLAG		;clear the retry flag
	JSR	PC,MOVSTA	;perform the motion
	TST	RPFLAG		;did we go through a retry?
	BNE	2$		;yes, we did
	CMP	INTPTR,(SP)+	;no, satisfactory move(check if move incremented
				;pointers
	BNE	1$		;yes, don't add anything
	CLR	@INTPTR		;no, clear next two words
	ADD	#2,INTPTR
	CLR	@INTPTR
	ADD	#2,INTPTR
1$:	RTS	PC		;return
2$:	MOV	SVPTR,INTPTR	;we went through a retry, back up
	TST	(SP)+		;pop the stack
	RTS	PC
DATA
SVPTR:	0			;used in case we do a RETRY$G
RPFLAG:	0			;checks if we did a RETRY$G
CODE
⊗ ;
GATHER:	FETCH <R0>
	MOV  #FPPTR,R1	;address of FP buffer
	MOV  #INTPTR,R2	;address of INTEGER buffer
	JSR  PC,@LGATHER	; now go call the appropriate routine
	RTS  PC

RFORCE:	SNDINT #XRFORCE		;send back a xrforce
	MOV  #INTPTR,R1		;address of integer buffer
	JSR  PC,@LRFORCE
	CCC
	RTS PC

SETSTF:	MOV  (R3)+,-(SP)	; save trans address
	MOV  #1$+24.,R0		; address of arguments
	MOV  #6,R1		; six of them
2$:	LDF  @(R3)+,AC0		; get the argument
	STF  AC0,-(R0)		; put in the right place
	SOB  R1,2$
;	MOV  #1$,R0		; let R0 point to the right place
				; R0 will be pointing to the right place
	MOV  (SP)+,R1		; R1 has address of trans
	JSR  PC,@LSETSTF	; jump into the arm code
	CCC
	RTS  PC			; and return
DATA
1$:	.BLKW	12.		; space for 6 real numbers
CODE
; supplementary functions: uparrow,dwnarrow,alpha,dollar,swap,vneg,vsmul,ftof
UPARROW: MOV	#ZHAT,-(R3)	; ↑ z-axis pointing upward, current frame or trans
	MOV	2(R3),R0	; get original trans value
	LDF	(R0),AC0
	MULF	AC0,AC0		; (1,1)↑2
	LDF	4(R0),AC1
	MULF	AC1,AC1		; (2,1)↑2
	ADDF	AC1,AC0		; ACO←(1,1)↑2+(2,1)↑2
	CMPF	C0001,AC0	; If AC0<C001 skip ahead
	CFCC
	BGT	1$
	CLRF	AC0
	SUBF	10(R0),AC0	; -(3,1)
	JSR	PC,@LASIN	; take arc-sin
	BR	2$
1$:	LDF	34(R0),AC0
	LDF	30(R0),AC1
	JSR	PC,@LATAN2	; take arc-tan2( (2,3),(1,3))
2$:    	JSR	PC,GETSCA	;R0 ← -(R3) ← LOC[new scalar block]
	STF	AC0,@(R3)	;Store result
	BR	DW3		;produce the rot

DOLLAR:	MOV	#NILROT,-(R3)	; $ station orientation, i.e. nilrot
	BR	DW2

ALPHA:	MOV	#ZHAT,-(R3)	; bgrasp orien at bpark, e.e. rot(zhat,180)
	BR	DW1

DWNARROW: MOV	#YHAT,-(R3)	; ↓ bpark orien, i.e. rot(yhat,180)
DW1:	MOV	#F180,-(R3)	; rot of 180 deg
DW3:	JSR	PC,VSAXWR	; return rot(vect,180) on stack
DW2:	JSR	PC,SWAP		; turn the top two elements around
	JSR	PC,TPOS		; take the position value of previous frame
	JSR	PC,TMAKE	; produce the transform
	RTS	PC		; and return

VNEG:	MOV	(R3),-(R3)	; copy the vector on the stack
	MOV	#NILVEC,2(R3)	; put in nilvector
	JMP	VSUB

VSMUL:	JSR	PC,SWAP		; reverse the two top elements
	JMP	SVMUL		; exit from SVMUL

SWAP:	MOV	(R3),-(SP)	; switch positions of top two elementsof stack
	MOV	2(R3),(R3)
	MOV	(SP)+,2(R3)
	RTS	PC

WRT:	JSR	PC,TORIEN	; v wrt t = orient(t)*v
VFREL:	JSR	PC,SWAP		; v rel f = t*v
	JMP	TVMUL

FTOF:	JSR	PC,SWAP		;t1→t2 = inv(t1)*t2
	JSR	PC,TINVRT
FFREL:	JSR	PC,SWAP		; f rel t = t*f
	JMP	TTMUL
				; take positions of three frames and put them
				; to the stack
FCONSTR: MOV	(R3)+,-(SP)	; save top two elements
	MOV	(R3)+,-(SP)
	JSR	PC,TPOS		; find position of frame 1
	MOV	(SP)+,-(R3)
	JSR	PC,TPOS		; find position of frame 2
	MOV	(SP)+,-(R3)
	JSR	PC,TPOS		; find position of frame 3
	JMP	CONSTR

; functions: sqrt,sin,cos,asin,acos,tan,atan2,log,exp
PSQRT:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,SQRT
	JMP	SRET

PSIN:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,SIN
	JMP	SRET

PCOS:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,COS
	JMP	SRET

PTAN:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,TAN
	JMP	SRET

PASIN:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,ASIN
	JMP	SRET

PACOS:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,ACOS
	JMP	SRET

PATAN2:	JSR	PC,SWAP
	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,ATAN2
	JMP	SRET

PLOG:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,LOG
	JMP	SRET

PEXP:	LDF @(R3)+,AC0	;AC0 ← arg
	JSR	PC,EXP
	JMP	SRET
; armreach- can arm reach here?
; routine checks if arm can reach location specified on the stack
; it leaves true or false on the stack

ARMREACH:
	PUSH	<R2>		; save R2
	MOV	#28.,R0		; angle list
	JSR	PC,GTFREE
	PUSH	<R0>
	MOV	#14.,R0
	JSR	PC,GTFREE	; pointer list
	PUSH	<R0>
	MOV	2(SP),R1	;R1←address of angle values
	MOV	#14.,R2		; shift 14 addresses
1$:	MOV	R1,(R0)+
	ADD	#4,R1
	SOB	R2,1$
	MOV	(R3)+,R0	;R0←LOC[trans]
	MOV	(SP),R1		;R1←address pointers
	FETCH	<R2>		;R2←mechanism
;;;	JSR	PC,LSOLVE	; jump into armsolution routine
	PUSH	<R0>		; save error code
	JSR	PC,GETSCA	; R0←-(R3)←LOC[scalar]
	MOV	ONE,(R0)+	; put scalar as true
	CLR	(R0)
	TST	(SP)+		; check error code from SOLVE
	BEQ	2$		; there was no error
	CLR	(R3)		; oops there was an error
2$:	POP	<R0>
	JSR	PC,RLFREE	; release theta pointer space
	POP	<R0>
	JSR	PC,RLFREE	; release space for theta angles
	POP	<R2>		; restore R2
	CCC
	RTS	PC		; return
; procedure handling: GTBLK

GTBLK:
COMMENT ⊗
	 GTBLK n ..... q 
	n is size of the block of pcode to be copied
	 ..... is n words of information
	 the address of the block is to be put at the location of q + offset q
	⊗
	FETCH	<R0>		; get size of the block to get
	MOV	R0,R2		;
;	ADD	R0,R0		; get size in bytes
	JSR	PC,GTFREE	; get the size we need
	MOV	R0,-(SP)	; save the address of the block
1$:	FETCH	<R1>		; get word to transfer
	MOV	R1,(R0)+	; transfer to new area
	SOB	R2,1$
	MOV	@IPC(R4),R1	; now get the offset in which to stick the address of this block
	ASL	R1		; get it in bytes
	ADD	IPC(R4),R1	; get the absolute address
	BMPIPC
	MOV	(SP)+,(R1)	; write into the pcode ####### ... careful !
	RTS	PC		; and return

; more stack ops: gtint,gvals,chngs

APUSHOFFSET:
	JSR PC,PUSHINITI	; push index onto stack
PUSHOFFSET:
AREF:
; The argument is an integer. Make a scalar record and store the offset value
; on that stack.
; this routine is used in conjunction with GVALS and CHNGS
	JMP PUSHINTI

GTINT:	LDF	@(R3)+,AC0	;Get value of top element of stack
	STCFI	AC0,R0		;Convert it to integer & store it in R0
	RTS 	PC

GVALS:	JSR	PC,GTINT	; get the value of variable whose offset is on stack
	JMP	GVAL0

CHNGS:	JSR	PC,GTINT	; change the value of the variable whose offset is on stack
	JMP	CHNG0

GTARGS:	JSR	PC,GTINT	; take the value from the stack and convert to integer
	JMP	GETARG

DATA
HLTMSG:	0
CODE
; components of data types: CHCMP,GTCMP
; appropriate component of element whose level offset is on stack is changed
; or obtained

CHCMP:	FETCH	<R0>
	DEC	R0		;reduce by 1
	ASH	#2,R0		;multiply by 4
	MOV	R0,-(SP)
	JSR	PC,GTARGS	; R0←[env entry]
	MOV	R0,-(SP)	; save for later use
	JSR	PC,GVAL1	; (R3)←LOC[vect or trans]
	MOV	(R3),R0	
	CMPB	#VCTID,TAGID(R0); check if it is a vector
	BEQ	1$		; yes it is
	ADD	#44,2(SP)	; no, it isnt
1$:	JSR	PC,SWAP		; trade two top elements of stack so scalar on top
	LDF	@(R3)+,AC0	; AC0← value of component to be changed
	MOV	2(SP),R0	; put component into R0
	ADD	(R3),R0		; get effective address of component
	STF	AC0,(R0)	; (R3) has appropriate value
	MOV	(SP)+,R0	; get back environment entry
	JSR	PC,CHNG1	; and change the value
	TST	(SP)+		; pop the stack
	RTS	PC

CHTPOS:	JSR	PC,GVALS
	MOV	#44,R0		; put the offset into R0
	ADD	(R3)+,R0	; R0←LOC[x-comp of trans]
	MOV	(R3)+,R1	; R1←LOC[x-comp of vector]
	PUSH	<R2>
	MOV	#3,R2		; use R2 as counter
1$:	LDF	(R1)+,AC0
	STF	AC0,(R0)+
	SOB	R2,1$
	POP	<R2>
	RTS	PC

CHTORIENT:
	JSR	PC,GVALS
	MOV	(R3)+,R0	;R0←[LOC trans]
	MOV	(R3)+,R1
	PUSH	<R2>		;use R2 as counter
	MOV	#9.,R2		;transfer 9 elements
1$:	LDF	(R1)+,AC0
	STF	AC0,(R0)+
	SOB	R2,1$
	POP	<R2>
	RTS	PC

GTXC:	CLR	-(SP)
	BR	GTCMP0
GTYC:	MOV	#4,-(SP)
	BR	GTCMP0
GTZC:	MOV	#10,-(SP)
GTCMP0::MOV	(R3),R0
	ADD	(R3)+,(SP)	; save on the stack
	CMPB	#VCTID,TAGID(R0); is it a vector?
	BEQ	1$		; yes, it is
	ADD	#44,(SP)	; no, it is a trans
1$:	JSR	PC,NOCMP	;dont compact for a bit
	JSR	PC,GETSCA	; R0←(R3)←LOC(scalar)
	MOV	(SP)+,R1	; r1←LOC[element]
	LDF	(R1),AC0
	STF	AC0,(R0)	;get the appropriate value
	JSR	PC,YESCMP	;allow compacting
	RTS	PC
; return from POINTY : pdone 

PDONE:
	MOV RF,SP		;Restore stack
	MOV -2(SP),RF		;RF ← old PC
	RTS RF			;Just return